/**********************************************************************
* 文件名：MqModel.h
* 创建日期：2021-06-16 13:23
* 作者：李志勇
* 邮箱：18771909050@163.com
* 版权声明：Copyright (c) 2021 zhiyongli Technology (China) Limited.
* All rights reserved.
* 修改记录:
***********************************************************************/
#include "MqController.h"
#include <QHostAddress>

#include "qamqpclient.h"
#include "qamqpexchange.h"
#include "qamqpqueue.h"

MqController::MqController()
{
    m_mqmodel.Read(m_save_name);
}

MqController::~MqController()
{
    if (!m_client)
    {
        m_client->disconnectFromHost();
        m_client->disconnect();
    }
}

void MqController::CreateConnect()
{
    if (!m_client)
    {
        m_client = std::make_shared<QAmqpClient>();
    }

    if (m_client->isConnected())
        return;

    connect(m_client.get(), SIGNAL(connected()), this, SLOT(slot_connect()), Qt::UniqueConnection);
    connect(m_client.get(), SIGNAL(disconnected()), this, SLOT(slot_disconnect()), Qt::UniqueConnection);

    m_client->setVirtualHost(m_mqmodel.m_virtual_host);
    m_client->setUsername(m_mqmodel.m_user_name);
    m_client->setPassword(m_mqmodel.m_password);

    m_client->connectToHost(QHostAddress(m_mqmodel.m_host_name), m_mqmodel.m_port);
}

void MqController::DisConnect()
{
    if (!m_client)
        return;

    m_client->disconnectFromHost();
}

void MqController::CreateExchange()
{
    if (!m_client)
    {
        emit signal_exchangeDeclared(false, "创建交换失败，请先建立连接！");
        return;
    }

    if (m_exchange)
    {
        return;
    }


    m_exchange = m_client->createExchange(m_mqmodel.m_exchange_name);

    connect(m_exchange, SIGNAL(declared()), this, SLOT(slot_exchangeDeclared()), Qt::UniqueConnection);

    ///< 此设置在服务器端有对一个交换时，设置失败并且造成发送数据失败导致连接断开 TODO
    m_exchange->declare(m_mqmodel.m_exchange_type, m_mqmodel.m_exchange_option);

    CreateQueue();
}

void MqController::CreateQueue()
{
    if (!m_client)
    {
        emit signal_queueDeclared(false, "创建队列失败，请先建立连接！");
        return;
    }

    if (m_queue)
        return;

    m_queue = m_client->createQueue(m_mqmodel.m_queue_name);
    m_queue->declare(m_mqmodel.m_queue_option);

    connect(m_queue, SIGNAL(declared()), this, SLOT(slot_queueDeclared()), Qt::UniqueConnection);
    connect(m_queue, SIGNAL(messageReceived()), this, SLOT(slot_message_received()), Qt::UniqueConnection);
}

void MqController::sendMsg(const QString &msg)
{
    sendMsg(msg, m_mqmodel.m_routing_key);
}

void MqController::sendMsg(const QString &msg, const QStringList &routingKey)
{
    if (!m_exchange)
        return;

    for (const auto& key : routingKey)
        m_exchange->publish(msg, key);
}

void MqController::set_host_name(const QString &host_name)
{
    m_mqmodel.m_host_name = host_name;
}

QString MqController::get_host_name() const
{
    return m_mqmodel.m_host_name;
}

void MqController::set_port(quint16 port)
{
    m_mqmodel.m_port = port;
}

quint16 MqController::get_port() const
{
    return m_mqmodel.m_port;
}

void MqController::set_virtual_host(const QString &virtual_host)
{
    m_mqmodel.m_virtual_host = virtual_host;
}

QString MqController::get_virtual_host() const
{
    return m_mqmodel.m_virtual_host;
}

void MqController::set_user_name(const QString &user_name)
{
    m_mqmodel.m_user_name = user_name;
}

QString MqController::get_user_name() const
{
    return m_mqmodel.m_user_name;
}

void MqController::set_password(const QString &password)
{
    m_mqmodel.m_password = password;
}

QString MqController::get_password() const
{
    return m_mqmodel.m_password;
}

void MqController::set_exchange_name(const QString &exchange_name)
{
    m_mqmodel.m_exchange_name = exchange_name;
}

QString MqController::get_exchange_name() const
{
    return m_mqmodel.m_exchange_name;
}

void MqController::set_exchange_type(QAmqpExchange::ExchangeType type)
{
    m_mqmodel.m_exchange_type = type;
}

QAmqpExchange::ExchangeType MqController::get_exchange_type() const
{
    return m_mqmodel.m_exchange_type;
}

void MqController::set_exchange_durable(bool is_durable)
{
    m_mqmodel.m_exchange_option.setFlag(QAmqpExchange::Durable, is_durable);
}

bool MqController::get_exchange_durable() const
{
    return m_mqmodel.m_exchange_option.testFlag(QAmqpExchange::Durable);
}

void MqController::set_exchange_autoDelete(bool is_autoDelete)
{
    m_mqmodel.m_exchange_option.setFlag(QAmqpExchange::AutoDelete, is_autoDelete);
}

bool MqController::get_exchange_autoDelete() const
{
    return m_mqmodel.m_exchange_option.testFlag(QAmqpExchange::AutoDelete);
}

void MqController::set_queue_name(const QString &queue_name)
{
    m_mqmodel.m_queue_name = queue_name;
}

QString MqController::get_queue_name() const
{
    return m_mqmodel.m_queue_name;
}

void MqController::set_queue_durable(bool is_durable)
{
    m_mqmodel.m_queue_option.setFlag(QAmqpQueue::Durable, is_durable);
}

bool MqController::get_queue_durable() const
{
    return m_mqmodel.m_queue_option.testFlag(QAmqpQueue::Durable);
}

void MqController::set_queue_exclusive(bool is_exclusive)
{
    m_mqmodel.m_queue_option.setFlag(QAmqpQueue::Durable, is_exclusive);
}

bool MqController::get_queue_exclusive() const
{
    return m_mqmodel.m_queue_option.testFlag(QAmqpQueue::Durable);
}

void MqController::set_queue_autoDelete(bool is_autoDelete)
{
    m_mqmodel.m_queue_option.setFlag(QAmqpQueue::AutoDelete, is_autoDelete);
}

bool MqController::get_queue_autoDelete() const
{
    return m_mqmodel.m_queue_option.testFlag(QAmqpQueue::AutoDelete);
}

void MqController::slot_connect()
{
    emit signal_connect(true, "连接成功！");

    CreateExchange();

    m_mqmodel.Save(m_save_name);
}

void MqController::slot_disconnect()
{
    if (m_exchange)
        m_exchange = nullptr;

    if (m_queue)
        m_queue = nullptr;

    emit signal_connect(false, "连接以断开");
}

void MqController::slot_exchangeDeclared()
{    
    emit signal_exchangeDeclared(true, "交换创建成功!");
}

void MqController::QueueBind()
{
    if (!m_queue)
        return;

    // 开启消费
    m_queue->consume(QAmqpQueue::coNoAck);

    // 绑定队列的 bingkey
    for(const auto& severity : m_mqmodel.m_binding_key)
    {
        m_queue->bind(m_mqmodel.m_exchange_name, severity);
    }
}

void MqController::slot_queueDeclared()
{
    QueueBind();

    emit signal_queueDeclared(true, "队列创建成功");
}

void MqController::slot_message_received()
{
    QAmqpQueue *temporaryQueue = qobject_cast<QAmqpQueue*>(sender());
    if (!temporaryQueue)
        return;

    QAmqpMessage message = temporaryQueue->dequeue();

    QString msg = "Recv: [x] " + message.routingKey() + ":" + message.payload();

    emit signal_message_received(msg);
}
